//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
using ManagementStudioServices.Interfaces;
using Microsoft.Research.ScientificWorkflow.ManagementStudioModels;
using Microsoft.Research.ScientificWorkflow.UIDesigner.WpfComposite;
using SR = Microsoft.Research.DataLayer;
using Microsoft.Research.ScientificWorkflow.TridentUtilities;

namespace Microsoft.Research.ScientificWorkflow.ManagementStudioControls.WorkflowManagerModule
{
    /// <summary>
    /// The presenter for the view which is displayed as a nested control in the available workflows listview.
    /// </summary>
    public class WorkflowJobListPresenter : INotifyPropertyChanged
    {
        /// <summary>
        /// The workflow manager service instance.
        /// </summary>
        private IWorkflowManagerService workflowManagerService;

        /// <summary>
        /// Flag to check if items were retreived in the query. 
        /// </summary>
        private bool emptyList;

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="container">The unity container.</param>
        /// <param name="view">The view.</param>
        /// <param name="service">The workflow manager service.</param>
        public WorkflowJobListPresenter(WorkflowJobListView view, IWorkflowManagerService service)
        {
            this.View = view;
            view.Presenter = this;
            this.workflowManagerService = service;
            this.Items = new ObservableCollection<object>();

            this.ShowProvenanceDataCommand = new DelegateCommand<JobViewModel>(this.ExecuteShowProvenanceDataCommand);
        }


        /// <summary>
        /// The items to be displayed in the table view.
        /// </summary>
        public ObservableCollection<object> Items { get; set; }

        /// <summary>
        /// The UI representation for the presenter.
        /// </summary>
        public UIElement View { get; private set; }

        /// <summary>
        /// The command for displaying provenance data.
        /// </summary>
        public ICommand ShowProvenanceDataCommand { get; private set; }

        /// <summary>
        /// Property to check if items were retreived in the query.
        /// </summary>
        public bool EmptyList
        {
            get
            {
                return this.emptyList;
            }
            private set
            {
                this.emptyList = value;
                this.OnNotifyPropertyChanged("EmptyList");
            }
        }

        /// <summary>
        /// Display the items in the table view.
        /// </summary>
        /// <param name="queryString"></param>
        public void DisplayItems(WorkflowViewModel selectedWorkflow)
        {
            Items.Clear();

            // Get the required items.
            Collection<SR.Job> jobList = this.workflowManagerService.GetWorkflowJobInstances(selectedWorkflow.WorkflowId);

            // Set the selected Index. Show the empty message if no items found.
            if (jobList != null && jobList.Count > 0)
            {
                this.EmptyList = false;

                // Add the items to the list.
                foreach (SR.Job job in jobList)
                {
                    try
                    {
                        JobViewModel jobViewmodel = new JobViewModel(job);
                        Items.Add(jobViewmodel);
                    }
                    catch (System.Security.SecurityException)
                    {
                        // Ignore: The user might not have permissions on the workflow.
                    }
                }
            }
            else
            {
                this.EmptyList = true;
            }
        }

        /// <summary>
        /// Display the provenance data for the selected job.
        /// </summary>
        /// <param name="selectedJob">The selected job.</param>
        private void ExecuteShowProvenanceDataCommand(JobViewModel selectedJob)
        {
            try
            {
                if (selectedJob != null)
                {
                    switch (selectedJob.MachineScheduled.MachineType)
                    {
                        case SR.MachineType.Virtual:
                            // Show message indicating that the provenance data is not stored as 
                            //  the machine is virtual and no blackboard service is enabled for execution.
                            TridentMessageBox.ShowTridentInformationMessageBox(
                                ManagementStudioResourceManager.GetString("ProvenanceDataNotAvailable"));
                            break;
                        case SR.MachineType.HPCCluster:
                        case SR.MachineType.Desktop:
                        case SR.MachineType.HPCComputeNode:
                        default:
                            this.workflowManagerService.OpenProvenanceWindow(selectedJob.JobId);
                            break;
                    }
                }
            }
            catch (TridentCustomException ex)
            {
                TridentMessageBox.ShowTridentErrorMessageBox(ex.Message);
            }
        }

        #region INotifyPropertyChanged Members

        /// <summary>
        /// The property changed event. Fired when a proprty value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Fires the property changed event.
        /// </summary>
        /// <param name="propertyName">Name of the property which has been modified</param>
        private void OnNotifyPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }
}
